package com.zjw.socket.demo.starter.service;

import com.zjw.socket.demo.starter.annotation.NonNull;
import com.zjw.socket.demo.starter.annotation.core.Service;
import com.zjw.socket.demo.starter.core.Reflector;
import com.zjw.socket.demo.starter.core.ioc.IOCBeanInfo;
import com.zjw.socket.demo.starter.core.ioc.IOCObserver;
import com.zjw.socket.demo.starter.core.ioc.IOCScope;
import com.zjw.socket.demo.starter.utils.LogUtils;
import io.vertx.core.Vertx;

public final class ServiceDispatcher {

  private static final String TAG = "ServiceStarterDispatcher";

  public static void dispatchService(Vertx vertx) {
    LogUtils.debug(TAG, "start");

    IOCScope.globalScope.registerRefreshObserver(new IOCObserver() {
      @Override
      public void onRefresh(Class<?> clazz) {
        if (!clazz.isAnnotationPresent(Service.class)) {
          return;
        }

        if (!(Reflector.isSuperClassOrInterfaceImpl(clazz, IService.class))) {
          throw new IllegalArgumentException("@service type must implements IService Interface");
        }
        IService service = (IService) Reflector.instanceEmptyConstructor(clazz);
        if (service == null) {
          throw new IllegalArgumentException("@service type must has empty constructor");
        }
        String name = service.getClass().getName();
        LogUtils.debug(TAG, "dispatcherService success " + name);
        service.onStart(vertx);
        IOCScope.globalScope.putBean(service.getClass(), service);
      }

      @Override
      public void onInject(IOCBeanInfo o) {

      }

      @Override
      public void onComplete() {

      }
    });

    LogUtils.debug(TAG, "end");
  }

  @NonNull
  public static <T extends IService> T optService(Class<T> clazz) {
    return IOCScope.globalScope.getBean(clazz);
  }
}
